<!DOCType html>
<!--
/*********************************************************
 * LICENSE: LICENSE-Free_CN.MD is CYL_Free-1.0
 *
 * Author: Numberwolf - ChangYanlong
 * QQ: 531365872
 * QQ Group:925466059
 * Wechat: numberwolf11
 * Discord: numberwolf#8694
 * E-Mail: porschegt23@foxmail.com
 * Github: https://github.com/numberwolf/h265web.js
 *
 * 作者: 小老虎(Numberwolf)(常炎隆)
 * QQ: 531365872
 * QQ群: 531365872
 * 微信: numberwolf11
 * Discord: numberwolf#8694
 * 邮箱: porschegt23@foxmail.com
 * 博客: https://www.jianshu.com/u/9c09c1e00fd1
 * Github: https://github.com/numberwolf/h265web.js
 *
 **********************************************************/
-->
<html>
<head>
    <link href="/favicon.ico" rel="icon" type="image/x-icon" />
    <meta charset="utf-8">
    <title>h265webjs - https://github.com/numberwolf/h265web.js</title>
    <meta charset="utf-8" name="author" content="ChangYanlong">
    <meta charset="utf-8" name="email" content="porschegt23@foxmail.com">
    <meta charset="utf-8" name="discord" content="numberwolf#8694">
    <meta charset="utf-8" name="github" content="https://github.com/numberwolf/h265web.js">

    <script src="dist/missile.js"></script>
    <script src="dist/h265webjs-v20221106.js"></script>

    <!--<script src="dist-multi-thread/missile-multi-thread.js"></script>
    <script src="dist-multi-thread/h265webjs-v20221106.js"></script>-->

    <style>
    </style>
</head>
<body>

<div style="width:1190px;background-color: #e9e9e9;">
    <div style="width:100%; height:20px; background-color:blue; color:white;">
        Player Area
    </div>
    <div style="width:100%;height:360px;overflow:hidden;">
        <div id="glplayer" style="width: 640px; height: 360px; background-color: #c9c9c9;float:left">
        </div>
        <div style="width: 550px; height: 360px; float:left; background-color:black; overflow:hidden;">
            <div style="width:100%; height:25px; background-color:blue; color:white;">
                1. Input Play URL (Editable)
            </div>
            <!-- <input id="url-input" style="width:100%; height: 20px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);" value="http://127.0.0.1/live/test.flv"> -->
            <input id="url-input" style="width:100%; height: 20px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);" value="example_normal/hevc_test_moov_set_head_16s.mp4">
            
            <!--<input id="url-input" style="width:100%; height: 20px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);" value="http://flv.vaiwan.com/live/test.live.flv">-->
            </input>
            <div style="width:100%; height:25px; background-color:blue; color:white;">
                2. Input Player Config (Editable)
            </div>
            <textarea id="config-input" style="width:100%; height: 280px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);">
{
    "player": "glplayer",
    "width": 640,
    "height": 360,
    "token" : "base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1",
    "extInfo" : {
        "probeSize" : 8192,
        "ignoreAudio" : 0,
        "coreProbePart" : 0.1,
        "autoPlay" : false,
        "cacheLength" : 50,
        "rawFps": 24
    }
}
            </textarea>
        </div>
    </div>

    <hr>

    <div style="width:100%;height: 200px; overflow: hidden">
        <div style="width:360px;height:200px;float:left;">
            <div style="width:100%; height:20px; background-color:blue; color:white;">
                SnapShot
            </div>
            <canvas id="snapshot-canvas" style="width: 360px; height: 180px; background-color: #000000;">
            </canvas>
        </div>
        <div style="width:830px;height:200px;background-color:black;float:left;">
            <div style="width:100%; height:20px; background-color:blue; color:white;">
                Event Log
            </div>
            <div style="width:100%;height:170px;overflow: hidden;">
                <textarea disabled="disabled" id="logger" style="width: 300px; height: 170px; background-color: #000000; color:white; float:left">
events
--------------------</textarea>
                <textarea disabled="disabled" id="logger-cache" style="width: 250px; height: 170px; background-color: #000000; color:white;float:left">
cache log</textarea>
                <textarea disabled="disabled" id="logger-pts" style="width: 250px; height: 170px; background-color: #000000; color:white; float:left">
pts log</textarea>
            </div>
        </div>
    </div>

    <hr>
    <button style="background-color:blue;color:white;" onclick="installPlayer()">1.Install</button>
    <button style="background-color:red;" onclick="releasePlayer()">2.Release</button>
    |
    <button onclick="playPausePlayer()" id="play-button" disabled>1.Play/Pause</button>
    <button onclick="seekPlayer()">2.Seek To 5s</button>
    <button onclick="mutePlayer()">3.Mute(Volume 0.0)</button>
    <button onclick="unmutePlayer()">4.Volume To 1.0</button>
    |
    <button onclick="fullscreenPlayer()">1.Fullscreen</button>
    |
    <button onclick="nextFrame()">1.Next Frame</button>
    <button onclick="snapshot()">2.Snapshot</button>
    <button onclick="playrate(0.5)">3.PlayRate 0.5</button>
    <button onclick="resize(640, 200)">resize640x200</button>

    <hr>

</div>

<pre>
--> 1.Install Player 
--> when [onReadyShowDone] happened 
--> 2.Play/Pause/Seek/Other operations
--> 3.Release Player
</pre>
<a href="https://github.com/numberwolf/h265web.js">https://github.com/numberwolf/h265web.js</a>

    <script>
        if((/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent))) {
            alert("safari");
        }

        const h265webURL = "https://github.com/numberwolf/h265web.js";
        
        var playerObj = null;
        var loggerObj = document.getElementById("logger");
        var loggerCacheObj = document.getElementById("logger-cache");
        var loggerPtsObj = document.getElementById("logger-pts");

        function clear() {
            window.STATICE_MEM_playerCount = -1;
            window.STATICE_MEM_playerIndexPtr = 0;
        } // end func clear

        function releasePlayer() {
            if (playerObj !== null) {
                playerObj.release();
                playerObj = null;
                // log
                loggerObj.value = h265webURL + "\r\nRelease done!";
                document.getElementById("play-button").setAttribute("disabled", "disabled");
            }
        }

        function installPlayer() {
            clear();

            const textarea_conf = document.getElementById("config-input");
            const textarea_conf_value = textarea_conf.value;
            const config = JSON.parse(textarea_conf_value);
            const play_url = document.getElementById("url-input").value;

            console.log(textarea_conf_value);
            console.log(config);
            console.log(play_url);

            /*
             *
             *
             * 1. create player object
             *
             *
             */
            playerObj = window.new265webjs(play_url, config);
            /*
             *
             *
             * 2. bind events
             *
             *
             */
            playerObj.onSeekStart = (pts) => {
                loggerObj.scrollNewest("\r\nonSeekStart:" + pts);
            };

            playerObj.onSeekFinish = () => {
                loggerObj.scrollNewest("\r\nonSeekFinish");
            };

            playerObj.onPlayFinish = () => {
                loggerObj.scrollNewest("\r\nonPlayFinish");
            };

            playerObj.onRender = (width, height, imageBufferY, imageBufferB, imageBufferR) => {
                loggerObj.scrollNewest("\r\nonRender");
            };

            playerObj.onOpenFullScreen = () => {
                loggerObj.scrollNewest("\r\nonOpenFullScreen");
            };

            playerObj.onCloseFullScreen = () => {
                loggerObj.scrollNewest("\r\nonCloseFullScreen");
            };

            playerObj.onSeekFinish = () => {
                loggerObj.scrollNewest("\r\nonSeekFinish");
            };

            playerObj.onLoadCache = () => {
                loggerObj.scrollNewest("\r\nonLoadCache");
            };

            playerObj.onLoadCacheFinshed = () => {
                loggerObj.scrollNewest("\r\nonLoadCacheFinshed");
            };

            playerObj.onReadyShowDone = () => {
                loggerObj.scrollNewest("\r\nonReadyShowDone:【You can play now】");
                document.getElementById("play-button").removeAttribute("disabled");
            };

            playerObj.onLoadFinish = () => {
                loggerObj.scrollNewest("\r\nonLoadFinish");

                playerObj.setVoice(1.0);
                mediaInfo = playerObj.mediaInfo();
                console.log("onLoadFinish mediaInfo===========>", mediaInfo);
                /*
                meta:
                    isHEVC: true
                    durationMs: 144400
                    fps: 25
                    sampleRate: 44100
                    size: {
                        width: 864,
                        height: 480
                    },
                    audioNone : false
                videoType: "vod"
                */
                let codecName = "h265";
                if (mediaInfo.meta.isHEVC === false) {
                    loggerObj.scrollNewest("\r\nonLoadFinish is Not HEVC/H.265");
                    codecName = "h264";
                } else {
                    loggerObj.scrollNewest("\r\nonLoadFinish is HEVC/H.265");
                }

                loggerObj.scrollNewest("\r\nonLoadFinish media Codec:" + codecName);
                loggerObj.scrollNewest("\r\nonLoadFinish media FPS:" + mediaInfo.meta.fps);
                loggerObj.scrollNewest("\r\nonLoadFinish media size:" + mediaInfo.meta.size.width + "x" + mediaInfo.meta.size.height);

                if (mediaInfo.meta.audioNone) {
                    loggerObj.scrollNewest("\r\nonLoadFinish media no Audio");
                } else {
                    loggerObj.scrollNewest("\r\nonLoadFinish media sampleRate:" + mediaInfo.meta.sampleRate);
                }

                if (mediaInfo.videoType == "vod") {
                    loggerObj.scrollNewest("\r\nonLoadFinish media is VOD");
                    loggerObj.scrollNewest("\r\nonLoadFinish media dur:" + Math.ceil(mediaInfo.meta.durationMs) / 1000.0);
                } else {
                    loggerObj.scrollNewest("\r\nonLoadFinish media is LIVE");
                }
            };

            playerObj.onCacheProcess = (cPts) => {
                loggerCacheObj.scrollNewest("onCacheProcess:" + cPts);
            };

            playerObj.onPlayTime = (videoPTS) => {
                if (mediaInfo.videoType == "vod") {
                    loggerPtsObj.scrollNewest("onPlayTime:" + videoPTS);
                } else {
                    // LIVE
                }
            };

            /*
             *
             *
             * 3. install player
             *
             *
             */
            playerObj.do();
        } // end func installPlayer

        function playPausePlayer() {
            if (playerObj !== null) {
                if (playerObj.isPlaying()) {
                    loggerObj.scrollNewest("\r\nplayerObj.pause()");
                    playerObj.pause();
                } else {
                    loggerObj.scrollNewest("\r\nplayerObj.play()");
                    playerObj.play();
                }
            }
        } // end func playPausePlayer

        function seekPlayer() {
            loggerObj.scrollNewest("\r\nplayerObj.seek(5)");
            if (playerObj !== null) {
                playerObj.seek(5);
            }
        } // end func seekPlayer

        function mutePlayer() {
            loggerObj.scrollNewest("\r\nplayerObj.setVoice(0)");
            if (playerObj !== null) {
                playerObj.setVoice(0);
            }
        } // end func mutePlayer

        function unmutePlayer() {
            loggerObj.scrollNewest("\r\nplayerObj.setVoice(1.0)");
            if (playerObj !== null) {
                playerObj.setVoice(1.0);
            }
        } // end func unmutePlayer

        function fullscreenPlayer() {
            loggerObj.scrollNewest("\r\nplayerObj.fullScreen()"); 

            if (playerObj !== null) {
                playerObj.fullScreen();
            }
        }

        function nextFrame() {
            loggerObj.scrollNewest("\r\nplayerObj.playNextFrame()"); 
            if (playerObj !== null) {
                playerObj.playNextFrame();
            }
        }

        function snapshot() {
            const snapCanvas = document.querySelector("#snapshot-canvas");
            if (playerObj !== null) {
                playerObj.snapshot(snapCanvas);
                loggerObj.scrollNewest("\r\nplayerObj.snapshot"); 
            }
        }

        function playrate(rate=1.0) {
            console.log(playerObj.player.videoTag);
            if (playerObj !== null) {
                let ret = playerObj.setPlaybackRate(rate);
                loggerObj.scrollNewest(
                    "\r\nplayerObj playrate:" 
                    + ' ret:' + ret
                    + ' tag:' + rate
                    + ' res:' + playerObj.getPlaybackRate()); 
            }
        }

        function resize(w, h) {
            if (playerObj !== null) {
                let ret = playerObj.resize(w, h);
                loggerObj.scrollNewest(
                    "\r\nplayerObj resize:" 
                    + ' ret:' + ret
                    + ' w:' + w
                    + ' h:' + h); 
            }
        }
        

        window.onload = function() {
            if (loggerObj === null) {
                loggerObj = document.getElementById("logger");
                loggerCacheObj = document.getElementById("logger-cache");
                loggerPtsObj = document.getElementById("logger-pts");
            }
            loggerObj.scrollNewest = function(val) {
                loggerObj.value += val;
                loggerObj.scrollTop = loggerObj.scrollHeight;
            };
            loggerCacheObj.scrollNewest = function(val) {
                loggerCacheObj.value = val;
                //loggerCacheObj.scrollTop = loggerCacheObj.scrollHeight;
            };
            loggerPtsObj.scrollNewest = function(val) {
                loggerPtsObj.value = val;
                //loggerPtsObj.scrollTop = loggerPtsObj.scrollHeight;
            };
        }; // end onload
    </script>
</body>
</html>






